<?php
/**
 * CreateTime: 2023/11/17 10:26
 * User:LinQ
 */

namespace App\Http\Service\Login;

use App\Func\System\ConfigFunc;
use App\Func\System\OperateLogFunc;
use App\Func\User\UserFunc;
use App\Models\Users\UsersModel;

class LoginService
{
    public function login($prams){
        /**
        {
            "account":"admin",
            "password":"6UPL1cITDnxfunG7IPS8rQ==",
            "sign":"FnnTl96VAn9OsUKWP5uNmgn5CqwRBFk1XFT48rdFjRKK1ZnZ60938Y6LJeL3lUTcfm0yxoLMJmtqdEc7yePR6hasR21zyVFYR9sAEldMk0kb4N/lyPTy/QuiBCTQwW0yCrPOe191lGq4z8PSXgSqcSHlwMTHD8/CM2lkjE2OlZnnX1ojWPWmK8k39N6i7tfFU0nbJeZc9qtCp+G38LdRSz/5fp2LZBQvcuNEgZrFItuNen+oKcNUxAixDlteaSwhVekDa137zw2mgpdD9UZY6vD9MP6MsguUKliHUzslPfissR/R8wrnP4YxV4E0wKu6933tW/saQvIauHMb/ivOjw=="
        }
         */
        // 首先，前端用 /user/u_pu 这个接口获取用户私有的公钥
        // 然后前端首先使用 AES256加密要传递过来的数据，并且保存加密使用的key，默认的iv为md5用户公钥,然后截取前16位,同时，使用公钥对key进行加密以后toBase64作为sign传递给服务端
        // get_iv($user->pu_key); aa4d136ee92d0678
        // aes_256_cbc_pkcs7_encode('admin',"123456",get_iv($user->pu_key)); 6UPL1cITDnxfunG7IPS8rQ==
        $userModel = new UsersModel();
        $user = $userModel->getUsersInfoByAccount($prams['account']);
        // 获取正确的签名  私钥解开后获取正确的aes key 123456
        $aesKey = rsa_decode($user->pv_key,$prams['sign']);
        // 加密以后 使用公钥加密这个aesKey pKeOnNDLDkh1rrkUcL/G/qxmLS5WUaEAMFw+B7rJqWnogUpqFosqVgvRfmvC4DnL/iEV/4gdZZtqcQPp2HjasHf03poSha2RGW9+SudCO4F4Am66MqVwS0yG91jMbT8ytJ5B/V9Nv3QsSHgqOswhsZezEfTT9pUc9aKcHQk9APqfvpoKsbMlQVSY5zNB+RsaSNxrDPzET7hQ2yMlcGXaqYuO+cQiY/exxVtpZTv3JAUWB6x5jLL8Cswp93fDLrSl5L7MbjgG+YGvGJqS17MyT95iqeWZJ9ehwRhydpx++NtfP0+YnidyobVrPQGT7WCIKH9Idk7g5TdgMWTH+qeqng==
        $prams['password'] = aes_256_cbc_pkcs7_decode($prams['password'],$aesKey,get_iv( str_replace(array("\n", "\r"), '', $user->pu_key)));
        if(!$user){
            // 客户端在请求时未提供有效的身份验证凭据 401 Unauthorized
             s_fail_return(null,trans('message.user_or_pass_err'),
                status:false,
                code:'Unauthorized',
                httpCode: 401
             );
        }else{
            $user->makeVisible('password');
            $checkPass = (new UserFunc())->checkHashPassByUser($prams['password'],$user->password);
            if(!$checkPass){
                s_fail_return(null,trans('message.user_or_pass_err'),
                    status:false,
                    code:'Unauthorized',
                    httpCode: 401
                );
            }
            // 更新用户最后登录日期
            $userModel->where('user_id',$user->user_id)->update([
                'staff_last_login_time' => date("Y-m-d H:i:s",time())
            ]);
            // 获取用户部门
            $userDepartments = UsersModel::with(['departments'=>function($query){
                $query->select([
                    'department.department_id',
                    'department.department_name',
                ]);
            }])->find($user->user_id);
            // 处理数据用于构建token
            $fmtDepartment = $userDepartments->toArray()['departments'];
            $departmentKey = [];
            foreach($fmtDepartment as $value){
                $departmentKey[] = [
                    'department_id' => $value['department_id'],
                    'pivot' => $value['pivot']
                ];
            }


            $user->makeHidden('password');
            // 数据都为base64以后的json $header.$payload.$ipInfo
            // 其中ipInfo user_id md5以后 aes256
            // $redisKey 用来保存私密内容
            // 签名的规则以 md5 json $payload作为加密key 使用 sha256进行加密以后转base64
            // 生成的token为
            // $header.$payload.$signature.$ipInfo
            $header = base64_encode(json_encode([
                'alg' => 'HS256',
                'typ' => 'JWT',
                'deadline' => time()+86400,
            ],256));
            $payload = base64_encode(json_encode([
                'user_id' => $user->user_id,
                'account' => $user->account,
                'union_id' => $user->union_id,
                'com_id' => $user->com_id,
                'hash' => hash_sign_x1($user->password.json_encode($departmentKey,256)),
            ],256));
            $aesKey = md5($user->user_id);
            $ipInfo = aes_256_cbc_pkcs7_encode(request()->ip(),$aesKey);
            $signature = base64_encode(hash_hmac('sha256', "$header.$payload.$ipInfo", md5(json_encode($payload,true)), true));
            $jwtToken = "$header.$payload.$signature.$ipInfo";

            OperateLogFunc::loginLog($user->user_id,1);

            s_c_return([
                'token' => $jwtToken,
                'dept_list' => $fmtDepartment,
                'time' => time(),
                'H_W'  => md5(time().random_bytes(5)),
                'C_H'  => md5(random_bytes(3))
            ],trans('message.login_ok'));
        }

    }

    public function getUserPuKey($prams)
    {
        // 首先，前端用 /sys/d_pu 这个接口获取公钥和iv（默认公钥在执行数据填充的时候会自动生成pu_key.pem,pv_key.pem并保存在seeder/system目录）
        // 然后前端首先使用 AES256加密要传递过来的所有数据，并且保存加密使用的key，同时，使用公钥对key进行加密以后toBase64作为sign传递给服务端
        $configFunc = new ConfigFunc();
        $defaultPuKey = $configFunc->getDefaultPvKey();
        $defaultIv = $configFunc->getDefaultIv();
        // 前端默认生成了一个 key 123456789 用于加密账号
        // aes_256_cbc_pkcs7_encode($prams['account'],"123456789",$defaultIv) eJK542d2ZLhQJgdAMsR27A==
        // 加密以后 使用公钥加密这个aesKey pKeOnNDLDkh1rrkUcL/G/qxmLS5WUaEAMFw+B7rJqWnogUpqFosqVgvRfmvC4DnL/iEV/4gdZZtqcQPp2HjasHf03poSha2RGW9+SudCO4F4Am66MqVwS0yG91jMbT8ytJ5B/V9Nv3QsSHgqOswhsZezEfTT9pUc9aKcHQk9APqfvpoKsbMlQVSY5zNB+RsaSNxrDPzET7hQ2yMlcGXaqYuO+cQiY/exxVtpZTv3JAUWB6x5jLL8Cswp93fDLrSl5L7MbjgG+YGvGJqS17MyT95iqeWZJ9ehwRhydpx++NtfP0+YnidyobVrPQGT7WCIKH9Idk7g5TdgMWTH+qeqng==
        // 获取正确的签名  私钥解开后获取正确的aes key 123456789
        $aesKey = rsa_decode($defaultPuKey,$prams['sign']);
        if(!$aesKey){
            // 客户端在请求时未提供有效的身份验证凭据 401 Unauthorized
            s_fail_return(null,trans('message.get_xx_err',[
                'name' => trans('key.pu_key')
            ]));
        }
        $prams['account'] = aes_256_cbc_pkcs7_decode($prams['account'],$aesKey,$defaultIv);
        $usersModel = new UsersModel();
        $user = $usersModel->getUsersInfoByAccount($prams['account']);
        if(!$user){
            // 客户端在请求时未提供有效的身份验证凭据 401 Unauthorized
            s_fail_return(null,trans('message.get_xx_err',[
                'name' => trans('key.pu_key')
            ]));
        }
        s_c_return([
            'pu_key' =>  preg_replace("/\r|\n/", "", $user->pu_key)
        ],trans('message.get_xx_ok',[
            'name' => trans('key.pu_key')
        ]));
    }
}
